package model
{
	import com.adobe.serialization.json.JSON;
	
	import flash.display.ActionScriptVersion;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	import flash.system.ApplicationDomain;
	import flash.utils.Timer;
	
	import org.osmf.events.TimeEvent;
	
	import view.character.CharacterExpBar;
	
	[Event(name="EVENT_INFO_UPDATE", type="model.ActionEvent")]
	
	public class Application extends EventDispatcher implements IEventDispatcher
	{
		private static var _instance:Application = null; 
		
		public static const STATE_UNKNOWN:int	= 0x0 ;
		public static const STATE_WAITING:int	= 2;//0x1<<1 ; 		//等待开始
		public static const STATE_READY_ME:int	=  4;//1<<2 ; 	//自己做好了准备 
		public static const STATE_READY_OTHER:int  = 8;//1<<3; 	//对手已做准备
		public static const STATE_START:int  = 16;//1<<4;			
		public static const STATE_WAIT_RES_OTHER:int  = 32;//1<<5;
		public static const STATE_SHOW_OTHER:int = 64;//1<<6;
		public static const STATE_SHOW_RESULT:int = 128;//1<<7;
		public static const STATE_TIMEOUT:int =256;//1<<8;
		public static const STATE_OTHER_EXIT:int= 512;//1<<9;
		public static const STATE_SHOW_USER_INFO:int = 1024;//1<<10;
		
		public static const RET_SUCC:int = 0 ;
		public static const RET_UNKNOWN:int = -1;
		public static const RET_NOLOGIN:int = -2;
		public static const RET_TIMEOUT:int = -3;
		public static const RET_DBERROR:int = -4;
		public static const RET_PARAMINVALID:int = -5;
		public static const RET_DICEINVALID:int = -6;
		
		public static const ACTION_GETUSERINFO:String = "GETUSERINFO";
		public static const ACTION_GETSTATE:String = "GETSTATE";
		public static const ACTION_LOGOUT:String = "LOGOUT";
		public static const ACTION_OPPLOGOUT:String = "OPPLOGOUT";
		public static const ACTION_READY:String = "READY";
		public static const ACTION_EXIT:String = "EXIT";
		public static const ACTION_OPEN:String = "OPEN";
		public static const ACTION_BOAST:String = "BOAST";
		public static const ACTION_OPPREADY:String = "OPPREADY";
		public static const ACTION_OPPEXIT:String = "OPPEXIT";
		public static const ACTION_OPPOPEN:String = "OPPOPEN";
		public static const ACTION_OPPBOAST:String = "OPPBOAST";
		
		public static const HEARTBEAT:int = 2000;//单位：毫秒
		
		
		
		
		private var _state:int; //游戏所处的状态
		private var _boastId:int = 0;
		
		private var _user:Character = null;
		private var _opponent:Character = null;
		
		//请求后端的组件
		private var _reqUrl:String = "";
		private var _urlReq:URLRequest = null;
		private var _urlLoader:URLLoader = null;
		
		private var _heartBeatTimer:Timer = new Timer(HEARTBEAT);
		
		
		
		public function get state():int
		{
			return _state;
		}


		public function get opponent():Character
		{
			return _opponent;
		}

		public function set opponent(value:Character):void
		{
			_opponent = value;
		}

		public function get user():Character
		{
			return _user;
		}

		public function set user(value:Character):void
		{
			_user = value;
		}

		public static function instance():Application
		{
			return _instance || (_instance = new Application());
		}
		
		public function Application(target:IEventDispatcher=null)
		{
			super(target);
		}
		
		public function heartBeat(e:TimerEvent):void
		{
			action(ACTION_GETSTATE);
		}
		
		public function init(url:String = ""):Boolean //初始化
		{
			if(url != "")
			{
				_reqUrl = url ;
			}
			
			_urlReq = new URLRequest(_reqUrl);
			_urlLoader = new URLLoader(_urlReq);
			configureListeners(_urlLoader);
			
			_heartBeatTimer.addEventListener(TimerEvent.TIMER, heartBeat);
			_heartBeatTimer.start();
			return true;
		}
		
		public function setCharacter(userId:int, opponentId:int):void
		{
			if(userId > 0 && _user == null)
			{
				_user = new  Character(userId);
			}
			
			if(opponentId > 0)
			{
				_opponent = new Character(opponentId);
			}
			action(ACTION_GETUSERINFO, {"userId":userId, "opponentId":opponentId});
		}
		
		public function setBoastId(boastId:int):void
		{
			_boastId = boastId;	
		}
		
		
		public function ready():Boolean //开始
		{
			if(_state == STATE_WAITING || _state == STATE_READY_OTHER || _state == STATE_SHOW_USER_INFO)
			{
				action(ACTION_READY);
				return true;
				
			}
			return false;
		}
		
		public function boast(count:int, no:int):Boolean //吹牛
		{
			if( _state == STATE_START || _state == STATE_SHOW_OTHER)
			{
				action(ACTION_BOAST, {"no":no, "count":count});
				return true;
			}
			return false;
		}
		
		public function open():Boolean //开底
		{
			if(_state == STATE_SHOW_OTHER)
			{
				action(ACTION_OPEN);
				return true;
			}
			return false;
		}
		
		public function exit():Boolean //退出
		{
			action(ACTION_EXIT); 
			return true;
		}
		
		
		private function action(actionName:String, params:Object = null):Boolean
		{
			var urlData:URLVariables = new URLVariables();
			urlData.data = JSON.encode({"action":actionName, "boastId":_boastId, "userId":_user.userId, "params":params});
			_urlReq.data = urlData;
			this._urlLoader.load(_urlReq);
			return true;
		}
		
		private function configureListeners(dispatcher:IEventDispatcher):void 
		{
			dispatcher.addEventListener(Event.COMPLETE, completeHandler);
			dispatcher.addEventListener(Event.OPEN, openHandler);
			dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
			dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
		}
		
		private function completeHandler(event:Event):void 
		{
			var loader:URLLoader = URLLoader(event.target);
			trace("completeHandler: " + loader.data);
			if(loader.data != null && loader.data != "")
			{
				trace("recv data:", loader.data);
				dispathMessage(loader.data);
			}
			
		}
		
		private function openHandler(event:Event):void 
		{
			trace("openHandler: " + event);
		}
		
		private function progressHandler(event:ProgressEvent):void 
		{
			trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);
		}
		
		private function securityErrorHandler(event:SecurityErrorEvent):void 
		{
			trace("securityErrorHandler: " + event);
		}
		
		private function httpStatusHandler(event:HTTPStatusEvent):void 
		{
			trace("httpStatusHandler: " + event);
		}
		
		private function ioErrorHandler(event:IOErrorEvent):void 
		{
			trace("ioErrorHandler: " + event);
		}	
		
		private function dispathMessage(msg:*):void
		{
			var obj:Object; 
			try
			{
				obj = JSON.decode(msg);
			}
			catch(err:Error)
			{
				trace(err.toString());
				return ;	
			}
			
			if(obj == null)
			{
				dispatchEvent(new Event(String(STATE_UNKNOWN)));
			}
			
			var action:String = obj["action"];
			var code:int = obj["code"];
			var data:Object = obj["data"];
			
			if(code == RET_SUCC)
			{
				var state:int = data["state"];
				if(STATE_START == state)
				{
					user.dices = data["dice"];
				}
				else if(STATE_SHOW_OTHER == state)
				{
					_opponent.dices = data["dice"];
				}
				else if(STATE_SHOW_RESULT == state)
				{
					_user.result = data["result"];
					_opponent.dices = data["opponent"];
				}
				
				if(action == ACTION_GETUSERINFO)
				{
					state = _state|STATE_SHOW_USER_INFO;
					for(var id:String in data)
					{
						if(int(id) == _user.userId)
						{
							_user.setInfo(data[id]);
						}
						else if(int(id) == _opponent.userId)
						{
							_opponent.setInfo(data[id]);
						}
					}
				}
				if(_state != state)
				{
					_state = state;
					dispatchEvent(new ActionEvent(_state, code));
				}
			}
			else
			{
				dispatchEvent(new ActionEvent(_state, code));
			}
			
		}
	}
}